Introduction
This is a home of the upcoming book «Enterprise Web Development. From Desktop to Mobile». The authors of this book are Yakov Fain, Victor Rasputnis, Viktor Gamov, and Anatole Tartakovsky. They all work for Farata Systems.
This book will be printed in the Summer of 2013, but you can enjoy read the current manuscript enterprisewebbook.com. The sources of this book are located at Github.
The book is released under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported license meaning you can both get a copy of the book for free or help to further improve it. This book will be printed and available for purchase via O’Reilly Media. Readers will have an option of purchasing this book in a number of digital formats.
What’s an Enterprise Web Application?
This book has the word Enterprise in its title, which needs to be explained, and we’ll do it by examples. Creating a Web application that will process orders is not the same as creating a Web site to publish blogs. Enterprise applications include company-specific workflows, and usually they need to be integrated with number of internal systems, data sources and processes.
Google Doc is not an enterprise Web application. But Google appliance integrating search operating on company documents, databases, processes, tickets, and providing collaboration is - it integrates consumer-workforce front office with what the company does (back office).
Google Maps is not an enterprise application. But Google Maps integrated with the company site used by insurance agents to plan daily route, scheduling, doing address verification and geo-coding is.
Just using a Web application in some business doesn’t make it an enterprise Web application. If you take Gmail as is, it won’t be an enterprise application until you integrate it into another process of your business.
Is an online game an enterprise application? It depends on the game. A multi-player online roulette game hooked up to a payment system, and maintaining users' accounts is an enterprise Web application. But playing Sudoku online doesn’t feel too enterprisey.
How about a dating Web site? If the site just offers an ability to display singles - it’s just a publishing site as there is not much of a business there. Can you turn a dating Web site into an enterprise application? It’s possible.
Some people will argue that an enterprise application must supports multiple users, high data load, be scalable, have business and persistence layers, offer professional support et al. We don’t believe that a Web application should do all this to qualify for the adjective enterprise.
Let’s create a simple definition of an enterprise Web application:
"An enterprise Web application is the one that helps an organization running its business online"
In this book we are going to build a Save the Child Web application that will allow people to register, donate, find local kids that need help, match donors and recipients, upload images, videos and display statistics. Would these feature make Save the Child an enterprise Web application? Yes, our non-for-profit organization that collects donations for ill kids is our enterprise.
During the last decade the authors of this book worked on many enterprise Web applications using variety of programming languages and frameworks: HTML, JavaScript, Java, and Flex to name a few. Apache Flex and Java produce compiled code that runs in a well known and predictable virtual machine (JVM and Flash Player respectively).
This book is about developing software using what’s known as HTML5 stack. But only the first chapter of this book will offer you an overview of the selected HTML5 tags and APIs. The second chapter is an advanced introduction to JavaScript. The rest of the chapters are about designing, re-designing, developing, and re-developing a sample Web site Save Sick Child. You’ll be learning whatever is required for building this Web application on the go.
You’ll be using dynamic HTML (DHTML), which is HTML5, JavaScript, and Cascading Style Sheets (CSS). We’ll add to the mix the XMLHttpRequest object that lives in a Web browser and communicates with the server without the need to refresh the entire Web page (a.k.a. AJAX). JSON will be our data format of choice for data exchange between the Web browser and the server.
|
|
It’s not possible to provide the detailed coverage of all programming languages, frameworks and tools used in this rather short book. You’ll need to do some additional reading with more in-depth coverage of certain topics. This book is for practitioner who need to learn while developing a project. |
From DHTML to HTML5
DHTML has been introduced in Microsoft Internet Explorer (IE) 5, and several years later it was substituted with a more popular acronym AJAX. Back in 1999 Microsoft introduced XMLHttpRequest object to allow the Web version of their mail client Outlook to update the browser’s window without the need to refresh the entire Web page. The market share of IE5 was about 90% at the time, and in enterprises it was literally the only approved browser.
Many years passed by and today’s Internet ecosystems changed quite a bit. Web browsers are a lot smarter and performance of JavaScript improved substantially. The browsers support 6-8-12 simultaneous connections per domain (as opposed to 2 five years ago), which gave a performance boost to all AJAX applications. At least one third of all Web requests is being made from smart phones or tablets. Apple Inc. started their war against browser’s plugins hence using embedded Java VM or Flash Player is not an option there. The growing need to support a huge variety of mobile devices gave another boost for HTML5 stack, which is supported by all devices.
But choosing HTML5 as the least common denominator that works in various devices and browsers means lowering requirements for your enterprise project. From the very beginning parameters like reliability, ability to adapt to different the screen sizes and densities will be simplified comparing to developing for one specific VM, device or OS. Instead of implementing these features, the functional specification will include testing under several Web browsers, in many different screen sizes and resolutions. HTML5 developers spend a lot more time in the debugger that people who develop for a known VM. Get ready to solving problems like a dropdown does not show any data in one browser while working fine in all others. Can you imagine a situation when the click event is not always generated while working in Java, Flex, or Silverlight? Get ready for such surprises while testing your DHTML application.
You’ll save some time because there is no need to compile JavaScript, but you’ll spend more time testing deployed code. The final deliverable of an HTML5 project may have as low as half of the functionality comparing to the same project developed for a VM. But you’ll gain a little better Web adaptability, easier implementation of full text search and mashups. The integration with other technologies will also become easier with HTML/JavaScript. If all these advantages are important to your application choose HTML5.
JavaScript will enforce its limitations on any serious and complex enterprise project. You can develop a number of fairly independent windows, but creating a well tested and reliable HTML5 takes time.
In this book we’ll be using some JavaScript frameworks - the are dozens of those on the market. Several of them promise to cover all the needs of your Web application. Overall, there are two main categories of frameworks:
a) Those that allow you to take an existing DHTML Web site and easily add new attributes to all or some page elements so they would start shining, blinking, or do some other fun stuff. Such frameworks don’t promote component-based development. They may not include navigation components, grids, trees, which are pretty typical for any UI of the corporate tasks. JQuery is probably the best representative of this group- it’s light (30Kb), extendable, and easy to learn.
b) Another group of frameworks offers rich libraries of high-level components and allow you to extend them.But overall, such components are supposed to be used together becoming a platform for your Web UI. These components process some events, offer support of the Model-View-Controller paradigm, have a proprietary way of laying out elements on the Web page, organize navigation et al. Ext JS from Sencha belongs to this group.
We’ll use both JQuery and Ext JS and will show you how to develop Web applications with each of these popular frameworks. JQuery is good for improving an existing JavaScript site. JQuery can be used to program about 80% of a Web site. You should use it for the look and feel support, which is what it’s meant for. But you can’t use it for building your application component model. The component model of Ext JS is applicable in about 20% of a Web site, which includes an application piece rather than just being a set of Web pages. Typically it’s a serious view navigator or a wizard to implement a serious business process or a workflow that includes a client’s part.
JavaScript frameworks are hiding from software developers all incompatibilities and take care of the cases when a Web browser doesn’t support some HTML5, CSS3, or JavaScript features yet.
High-level UI components and a workflow support are needed for a typical enterprise application where the user needs to perform several steps to complete the business process. And these 20% of an application’s code will require 80% of the project time of complex development. So choosing a framework is not the most difficult task. The main problem with DHTML projects is not how to pick the best JavaScript framework for development, but finding the right software developers. Lack of qualified developers increases the importance of using specialized frameworks for code testing. The entire code base must be thoroughly tested over and over again. We’ll discuss this subject in the Chapter 5 dedicated to test-driven development.
A JavaScript developer has to remember all unfinished pieces of code. Many things that we take for granted with compiled languages simply don’t exist in JavaScript. For example, in Java or C# just by looking at the method signature you know what are the data types of the method’s parameters. In JavaScript you can only guess if the parameter names are self descriptive. Take the Google’s framework GWT that allows developers write code in Java with auto-generation of the JavaScript code. Writing code in one language with further conversion and deployment in another one is a controversial idea unless the source and generated languages are very similar. We’re not big fans of GWT, because after writing the code you’ll need to be able to debug it. This is when a Java developer meets a foreign language JavaScript.The ideology and psychology of programming in JavaScript and Java are different. A person who writes in Java/GWT has to know how to read and interpret deployed JavaScript code. On the other hand, using TypeScript or CoffeeScript to produce JavaScript code can be a time saver.
The Ext JS framework creators decided to extend JavaScript introducing their version of classes and more familiar syntax for object-oriented languages. Technically they are extending or replacing the constructs of the JavaScript itself extending the alphabet. Ext JS recommends creating objects using ext.create instead of the operator new. But Ext JS is still a JavaScript framework.
JQuery framework substantially simplifies working with browser’s DOM elements and there are millions of small components that know how to do one thing well, for example, an image slider. But it’s still JavaScript and requires developers to understand the power of JavaScript functions, callbacks, and closures.
Should we develop in HTML5 if its standard is not finalized yet?
The short answer is yes. If you are planning to develop mainly for the mobile market, it’s well equipped with the latest Web browsers and if you’ll run into issues there. they won’t be caused by the lack of HTML5 support. In the market of the enterprise Web applications, the aging Internet Explorer 8 is still being widely used and they don’t support some of the HTML5 specific features. But it’s not a show stopper either.If you are using one of the JavaScript frameworks that offers cross-browser compatibility, most likely, they take care of IE8 issues.
The more conservative approach to achieving the browser compatibility is not by relying on the framework promises, but by testing and adjusting your application in different browsers. The chances are that you may need to be fixing the framework’s code here and there. Maintaining compatibility is a huge challenge for any framework’s vendor, which in some cases can consist of just one developer. You shouldn’t have hard feelings against the developers behind the framework of your choice. These guys simply don’t have time to fix everything. You need to form an attitude that a JavaScript framework is similar to a good Legos set that will require your creativity too. Don’t get angry. Cure the framework. Spend some time working on the framework, and then work on your application code. Ideally, submit your fixes back to the framework’s code base - most of them are open source.
If you are planning to write pure JavaScript, add a tiny framework Modernizr to your code base, which will detect if a certain feature is supported by the user’s Web browser, and if not - provide an alternative solution. We like the analogy with TV sets. People with latest 3D HD TV sets and those who have 50-year old black and white televisions can watch the same movie even though the quality of the picture will be drastically different.
Summary
If you are starting working on your first HTML5 enterprise project, get ready to solve the same tasks as Java, JavaFX, Silverlight, or Flexdevelopers face:
-
Reliability of the network communications. What if the data never arrive from/to the server? Is it possible to recover the lost data? Where they got lost? Can we re-send the lost data? What to do with duplicates?
-
Modularization of your application. If your application has certain rarely used menus don’t even load the code that handles this menu.
-
Perceived performance. How quickly the main window of your application is loaded to the user’s computer? How heavy is the framework’s code base?
-
Should you store the application state on the server or on the client?
-
Does the framework offer a rich library of components?
-
Does the framework support creation of loosely coupled application components? Is the event model well designed?
-
Does the framework of your choice cover most of the needs of your application, or you’ll need to use several frameworks?
-
Is well written documentation available?
-
Does the framework of your choice locks you in? Does it restrict your choices? Can you easily replace this framework with another one if need be?
-
Is there an active community to ask for help with technical questions?
We could continue adding items to this list. But our main message is that developing HTML5 applications is not just about adding tag video and canvas to a Web page. It’s about serious JavaScript programming.
Part 1: Desktop
Chapter 1. HTML5 and its New APIs
This is the first and only chapter in this book that’s dedicated to HTML5. You’ll get familiar with some new HTML tags that were introduced to make the markup more semantic and convenient. We’ll also provide a brief overview of selected APIs that are included in HTML5 spec (Web Storage, WebSQL, Web Sockets, and Web Workers).
The majority of the modern Web browsers already support the current version of HTML5 specification. The question is if the users of your Web application have or rather can have a modern browser installed on their device? There are two groups of users that will stick to the outdated browsers for some time:
-
Computer illiterate people who are afraid of installing any new software one their PCs. Especially, people of the older generation. `‘John, after the last visit of our grandson our computer works even slower than before. Please don’t let him install these new fancy browsers here. I just need my old Internet Explorer, access to Hotmail and Facebook’' .
-
Business users working for large corporations, where all the installations of the software on their PCs is done by professional sysadmins. They say, `‘We have 50000 PCs in or firm. An upgrade from Internet Explorer version 8 to version 9 is a major undertaking. Internal users work with about a hundred Web applications on a regular basis. They can install whatever browser they want, but if some of these application won’t work as expected, the users will flood us with support requests we’re not qualified to resolve’' . Hence the strategy of using the lowest denominator browser often wins.
In the worst case scenario, Web developers need to make both of these groups happy. Take an online banking - this old couple has to be able to use your Web application from their old PCs otherwise they can transfer their lifetime savings to a different bank which doesn’t require the later version of Firefox for online banking.
Does it mean that enterprise Web developers shouldn’t even bother using HTML5 that’s not 100% supported? Not at all. This means that a substantial portion of their application’s code will be will be bloated by the if-statements figuring out what this specific Web browser supports and providing several solutions that keep your application on float in any Web browser. This what makes the job of DHTML developers a lot more difficult than of, say Java developers who know exactly the environment where their code will work. Of you don’t install the JavaRuntime of version 1.6 our application won’t work. As simple as that. How about asking Java developers writing applications that will work in any runtime released during the last 10 years? No, we’re not that cruel.
Do you believe it would be a good idea for Amazon or Facebook to re-write their UI in Java? Of course not unless they want to loose half of their customers who will be scared to death after seeing the message of the 20-step Java installer asking for the access to the internals of their computer. Each author of this book is a Java developer, and we love using Java… on the server side. But when it comes to the consumer facing Web applications it’s just not there yet.
So what’s the bottom line? We have to learn how to develop Web application that won’t require installing any new software on the user’s machines. Today it’s DHTML or, let’s stick to the modern terminology, HTML5 stack.
In the unfortunate event of needing to support both new and old HTML and CSS implementations you can use HTML5 Boilerplate that is not a framework, but a template for creating a new HTML project that will support HTML5 and CSS3 elements but will work event in the hostile environments of the older browsers. It’s like broadcasting a TV show in HD, but letting the cavemen with the 50-year old black-and-white tubes watching it too.
HTML Boilerplate comes is a really simple way to start your project pre-packaged with solutions and workarounds offered by well known gurus in the industry. Make no mistake, your codebase may be larger that you wanted - for example, the initial CSS starts with 500 lines accommodating the old and new browsers, but it may be your safety net.
|
|
Watch this screencast by Paul Irish, a co-creator of HTML5 Boilerplate. You can also read the current version of the Getting started with HTML5 Boilerplate on Github. |
Overview of Selected HTML 5 Tags
In this section we’ll overview a small set of the new HTML5 tags and attributes that are very practical for enterprise Web developers. For example, we are not going to review the <canvas> tag that allows you to draw freely in a predefined rectangular area. But we will show you some HTML5 goodies that are practical and useful for Web forms.
HTML5 Forms: Brief Overview
It’s hard to imagine an enterprise Web application that is not using forms. At the very minimum the Contact Us form has to be there. A login view is yet another example of the HTML form that almost every enterprise application needs. Our sample application Save Sick Child will need it too.
We’ll start with the prompts. Showing the hints or prompts right inside the input field will save you some screen space. HTML5 has a special attribute placeholder.
HTML5 New APIs
TODO
Chapter 2. Advanced Introduction to JavaScript
This chapter is dedicated to the JavaScript programming language. Our challenging goal is “From Zero to Hero in 50 pages”. While in the future chapters you’ll see how JavaScript frameworks can greatly minimize the amount of the JavaScript code that you need to write manually, you still need to understand the language itself.
This chapter starts with basics of the language, but then it quickly progresses to such advanced topics as prototypal inheritance, callbacks and closures. If you prefer more fundamental and detail-oriented way of learning programming languages, read the book “Modern JavaScript. Develop and Design” by Larry Ullman or “JavaScript: The Definite Guide”, Sixth Edition by David Flanagan.
Besides the JavaScript coverage this chapter includes a section on the tools (IDEs, debuggers, Web inspectors et al.) that will make your development process more productive. In Chapter 3 we’ll start working on the first implementation of the Web site "Save Sick Child", which will include some JavaScript code.
JavaScript: A Brief History
The JavaScript programming language was designed in 1995 by Brendan Eich, who was working for Netscape Communication Corporation at the time. His goal was to allow developers create more interactive Web pages. Initially the name of this language was Mocha, then LiveScript, and finally Netscape agreed with Sun Microsystems, creator of Java (another new at the time language) to rename it to JavaScript.
A year later, the language was given to an international standards body called ECMA, which formalized the language into ECMAScript standard so that other browser vendors could create their implementation of this standard. ActionScript is a good example of another popular dialect of ECMAScript.
To learn more about the history of JavaScript from the source watch the Brendan Eich’s presentation “JavaScript at 17” at O’Reilly’s conference Fluent 2012.
Although the vast majority of today’s JavaScript code is being executed by the Web browsers some third-party tools also include JavaScript engines. For example, Google’s V8 JavaScript engine is used not only in the Chrome browser, but it’s a server-side way to run the code written in JavaScript framework node.js. Using the same programming language on the client and the server is the main selling point of node.js. Oracle’s Java Development Kit (JDK) 8 includes the JavaScript engine Nashorn that can run on both the server and the client computers.
In the 90th, JavaScript was considered a second class language used mainly for prettifying Web pages. In the beginning of the 21st Century the techniques known as AJAX (described in Chapter 4) made a significant impact to the way Web pages were built. With AJAX, the specific content inside the Web page could be updated without the need to make a full page refresh. Think of Google’s gmail that inserts just one line at the top of your input box when new email arrives - it doesn’t re-retrieve the entire content of your inbox from the server.
AJAX gave a second birth to JavaScript. But the vendors of Web browsers were no eager to implement the latest specifications of ECMAScript. Browsers’ incompatibility and lack of good development tools prevented JavaScript to become the language of choice for Web applications. Let’s not forget about the ubiquitous Flash Player – an excellent VM supported by all Web browsers. Rich Internet Applications written in ActionScript were compiled into the byte code and executed by Flash Player on the user’s machine inside the Web browser.
If AJAX saved JavaScript, then rapid proliferation of tablets and smartphones made it really hot. Today’s mobile devices come equipped with modern Web browsers and in the mobile world there is no need to make sure that your Web application will work in the 12 year old Internet Explorer 6. Adobe’s decision to stop supporting Flash Player in the mobile Web browsers is yet another reason to turn to JavaScript if your Web application has to be accessed from smartphones or tablets. The ECMASript, 5th Edition has been published in 2009 and is currently supported by all modern Web browsers. If you are interested in discovering if specific features of ECMAScript 5 are supported by a particular Web browser, check the latest version of the ECMAScript 5 compatibility table. At the time of this writing the snapshot of the Chrome Browser v. 22 looks as in Figure 2-1 below:
Figure 2-1. ECMAScript 5 Compatibility Sample Chart
JavaScript became the lowest common denominator available on thousands of different devices. Yes, the JavaScript engines are not exactly the same on thousands devices that people use to login to Facebook, but they are pretty close, and using some of the JavaScript frameworks spare you from worrying about their incompatibilities.
JavaScript is an interpreted language that arrives to the place of execution as text. The JavaScript engine optimizes and compiles the code before the execution. If the JavaScript engine is a part of a Web page, the browser will load and execute the JavaScript code embedded or referenced between the HTML tags <script> and </script>. JavaScript was originally created for Web browsers, which were supposed to display whatever content has successfully arrived. What if an image has not arrived from the server? You’ll see a broken image icon. What if not all JavaScript code has arrived to the browser? Well, the engine will try to execute whatever is available. The end users may appreciate such browser’s forgiveness when at least some content is available, but the software developers should be ready to spend more time debugging (in multiple browsers) the errors that could have been caught by compilers in other programming languages.
Why Declaring JavaScript Variables
JavaScript is a weakly typed language hence the developers don’t have a luxury of strong compiler’s help that Java or C# developers enjoy. This is easily explainable. Imagine that if in Java or C# instead of declaring variables of specific data types everything would be of type Object, and you could assign to it any value – a string, a number, or a custom object Person. This would substantially complicate the ability of the compiler to weed out all possible errors. You don’t need to declare variables in JavaScript – just assign a value and the JavaScript engine will figure out the proper type during the execution of your code.For example, the variable named girlfriend will have a data type of String:
girlfriendName=“Mary”;
Since I haven’t used the keyword var in front of girlfriend, this variable will have the global scope. Variables declared with var inside functions are local. Consider the following function declaration:
function addPersonalInfo(){ var address ="123 Main Street"; // local String variable age=25; // global Number variable var isMarried = true; // local boolean variable isMarried = "don't remember"; // now it's of String type }
The variables address and isMarried are visible only inside the function addPersonalInfo(). The variable age becomes global because of omission of the keyword var. In Chapter 3, you’ll see an example of how to limit the scope of the variables to avoid polluting the global name space.
The variable isMarried changes its type from Boolean to String during the execution of the above script, and JavaScript engine won’t complain assuming that the programmer knows what she’s doing. So be ready for the run-time surprises and allocate a lot more time for testing comparing to compiled languages.
Yet another moving part is the JavaScript engine where your code will run. Unless you are developing for strictly controlled enterprise environment you can’t assume that the end-user will have the same runtime as yours. This is yet another reason to test your code in multiple Web browsers.
Which IDE to Use
Selecting an Integrated Development Environment (IDE) that supports JavaScript is a matter of your personal preference. Since there is no compilation stage and most of your debugging will be done using the Web browser tools, picking a text editor that supports syntax highlighting is all that most developers need. For example, there is an excellent commercial text editor Sublime Text 2. Among many programming languages this editor understands the keywords of HTML, CSS, and JavaScript, and it offers not only syntax highlighting, context sensitive help, and auto-complete too.
If you are coming from the Java background, the chances are that you are familiar with free and open sourced Eclipse IDE. In this case install the Eclipse plugin VJET by eBay.
Oracle’s IDE NetBeans 7.3 and above support HTML5 and JavaScript development and includes JavaScript debugger that allows your code to connect to the Web browser, but you are debugging inside the IDE. If you prefer Microsoft technologies, they offer excellent JavaScript support in Visual Studio 2012.
In this book we’ll use an Eclipse-based Aptana Studio 3 IDE. Aptana Studio is available free of charge. Aptana Studio comes with embedded Web Server so you can test your JavaScript code without the need to start any additional software. In this chapter we’ll use Aptana Studio IDE to illustrate the features of JavaScript, and in the next chapter you’ll be working with a number of Aptana projects that will lead you through the development of the first version of our Save Sick Child Web application.
For the real world development we recommend using a commercial IDE WebStorm from JetBrains. In addition to smart context sensitive help, auto-complete, and syntax highlighting it offers HTML5 templates, a code coverage feature for unit testing that identifies the code fragment that haven’t been tested. All of the editors and IDEs listed here are either available for free or are priced in the area of $60 USD. Try them all and pick the one that best fits your coding habits.
Getting Familiar with Aptana IDE
Download and install Aptana Studio 3 from http://aptana.com. Start Aptana and close the start page it displays by clicking on the little X on the tab. Then customize the color theme of this IDE by clicking the rainbow-colored circle on its toolbar. We usually select the theme called Eclipse. After the first start of Aptana you’ll see the message on the left side that reads “There are no projects in your workspace. To get started, please create or import an existing one.”
If you want to start playing with the code samples that come with this book, click on the button Import Project, select the General | Archive file. Find the zip file you’d like to use, e.g. chapter2.zip, and press Finish. The project from the selected zip file will be imported into the Aptana’s workspace, which is nothing more than a folder on the disk where the source code will reside. When you work in Aptana IDE you see a set of views (panels). This set is called perspective. For Web projects Aptana uses Web perspective, which is indicated at the top right corner. Pressing the icon with a little pus sign at the top right allows to open another perspective with its own set of views.
Let’s get started with creating a project from scratch by pressing the button Create Project on the left. You could have also created a new Web Project using the File menu. On the next window you’ll need to select a wizard, and we’ll be always working with Web Projects throughout this book. The next window will offer you to select a project template - let’s stick to the simplest one - Default Project. Name it MyFirstProject.
To add an HTML file to this project select the menu File | New From Template | HTML | HTML5 Template. Aptana will offer you new_file.html the name of this file - no need to change it for now. Just press finish and you’ll see a window similar to the one shown on Figure 2-2.
Figure 2-2. Aptana IDE with one HTML5 file
Right-click on the new_file.html and select the menu Run as JavaScript Web project. Don’t get upset that there is no JavaScript code there yet - we’ll add it pretty soon. Aptana starts its built-in Web server that by default runs on the port 8020 (it’s configurable in Aptana Preferences). The Web browser opens up and displays the page that looks like the one in Figure 2-3. Aptana has used its default template to generate HTML file. The template can be changed to your liking, and you can read about it in Aptana’s documentation at http://bitly.com/LRqRdU.
Figure 2-2. Running MyFirstProject
|
|
To configure the Web Browser that Aptana should open by default, open its Preferences window and select the Web browser of your choice under the General section. Many examples in this chapter use the Firefox with installed add-on Firebug, so start with making Firefox your default browser. |
Adding JavaScript to HTML
If your JavaScript is a part of HTML document, typically, you’ll be adding your <script> tags at the end of HTML file. The reason is simple - your JavaScript code may be manipulating with HTML elements, and you want them to exist by the time the script runs. The other way to ensure that the code is not running unless the Web page has loaded is by catching window’s load event, and you’ll see such example later in this chapter in the section on browser’s events. Some JavaScript frameworks may have their own approach to dealing with HTML content and in Chapter 7 you’ll see that the main HTML file of the Web application written with Ext JS framework has <script> tags followed by the empty <body> tags. But let’s keep things simple for now.
Add the following fragment at the very end (right above the closing </body> tag) of the new_file.html from Figure 2-2.
<script> alert("Hello from JavaScript"); </script>
Run the new_file.html in Aptana and you’ll see the following output in your Web browser:
Figure 2-4. Running MyFirstProject with JavaScript at the bottom
Note that the Alert popup box is shown on top of the Web page that already rendered all of its HTML components. Now move the above code up to the end of the <head> section and re-run new_file.html. The picture is different now - the Alert box is shown before the HTML rendering is complete.
Figure 2-5. Running MyFirstProject with JavaScript at the top
In this simple example this doesn’t cause any malfunctioning of the code, but if our JavaScript would need to manipulate with HTML elements, we’d run into issues of accessing non-existent components.
|
|
Beside simple Alert box, JavaScript has Confirm and Prompt boxes, which allow asking OK/Cancel type of questions or require some input from the user. |
Debugging JavaScript in Web Browsers
The best way to learn any program is to run it step by step through a debugger. While some people appreciate using debuggers offered by Aptana, NetBeans, or Visual Studio, we prefer to debug using great tools offered by the Web browsers. Here’s what you’ve got:
-
Firefox: FireBug add-on
-
Chrome: Developer Tools
-
Internet Explorer: F12 Developer Tools
-
Safari: the menu Develop
-
Opera Dragonfly
We’ll be doing most of the debugging in FireBug or Chrome Developer Tools. Both of them provide valuable information about your code and are easy to use. To get FireBug go to www.getfirebug.com and press the red button Install Firebug and follow the instructions. In Firefox, open the Firebug panel from the menu View.
Figure 2-6. FireBug Console
Select the Console option on the Firebug toolbar and enter alert("Hello from JavaScript") after the >>> sign and you’ll see the Alert box. To enter multi-line JavaScript code press the little circle with a caret at the bottom right corner and FireBug will open a panel on the right, where you can enter and run your JavaScript code.
This was probably the last example where we used the Alert() popup box for debugging purposes. All JavaScript debuggers support the console.log() for printing debug information. Consider the following example that illustrate strict equality operator ===. Yes, it’s three equal signs in a row. This operator evaluates to true if the values are equal and the data types are the same.
var age=25; var ageStr="25"; if (age==ageStr){ console.log("The values of age and ageStr are equal"); } if (age===ageStr){ console.log("The values of age and ageStr are strictly equal"); } else{ console.log ("The values of age and ageStr are not strictly equal"); }
Running this code in the FireBug console produces the following output:
Figure 2-7. Using console.log() for the debug output
|
|
You can also use console.info(), console.debug(), and console.error() so debuggers may highlight the output with different colors or mark with different icons. |
|
|
For more information about debugging JavaScript refer to the code samples illustrated in Figure 2-8 and 2-9. |
JavaScript Functions. Gentle Introduction
Now comes the chicken or the egg dilemma. What should we explain first - functions or objects? Understanding of objects is needed for some of the function code samples and visa versa. We’ll start with simple function use cases, but will be switching to objects as needed.
Many of the readers can have experience with object-oriented languages like Java or C#, where classes can include methods implementing required functionality. Then these methods can be invoked with or without instantiation of the objects. If a JavaScript object includes functions they are called methods. But JavaScript functions don’t have to belong to an object. You can just declare a function and invoke it. Just like this:
//Function declaration function calcTax (income, dependents){ var tax; // Do stuff here return tax; } //Function invocation calcTax(50000, 2); var myTax = calcTax(50000,2);
Please note that the data types of the function parameters income and dependents are not specified. We can only guess that they are numbers based on their names. If a software developer won’t bother giving meaningful names to function parameters, the code becomes difficult to read. After the function calcTax() is invoked and complete, the variable myTax will have the value returned by the function. In the above code sample the JavaScript engine will not evaluate the function calcTax() until it’s actually invoked.
Another important thing to notice is that our function has a name calcTax. But this is not always the case - JavaScript allows functions to be anonymous. If you see the line of code where the keyword function is preceded by any other character this is not a function declaration, but a function expression. Consider the following variation of the tax calculation sample:
//Function expression var doTax=function (income, dependents){ //do stuff here return tax; } //Function invocation var myTax=doTax(50000,2);
In the code above the function keyword is being used in the expression - we assign the anonymous function to the variable doTax. After this assignment just the text of the function is assigned to the variable doTax - the anonymous function is not being invoked just yet. It’s important to understand that even though the code of this anonymous function ends with return tax; actually, the tax calculation and return of its value is not happening until the doTax() is invoked. Only then the function is evaluated and the variable myTax will get whatever value this function returns.
Yet another example of a function expression is when it’s placed inside the grouping operator - parentheses as shown below:
(function calcTax (income, dependents){ // Do stuff here });
Another interesting concept of JavaScript is self-executing functions. Adding an extra pair of parentheses will cause the function expression located in the first set of parentheses to be executed right away.
(function calcTax (income, dependents){ // Do stuff here })();
The first set of parentheses hides its internal code from the outside world creating a scope or a closed ecosystem, where the function’s code will operate. Try to add a line invoking this function after the last line in the above code sample, e.g. calcTax(50000,2), and you’ll get an error - "calcTax is not defined". There is a way to expose some of the internal content of such a closure and you’ll see how to do it later in this chapter.
JavaScript Objects. Gentle Introduction
JavaScript objects are simply unordered collections of properties. You can assign new or delete existing properties from the objects during the runtime whenever you please. In classical object oriented languages there are classes and there are objects. For example, based on one Java a class you can create multiple instances of its objects.
In JavaScript you can create objects using one of the following methods:
-
Using object literals
-
Using new Object() notation
-
Using Object.create()
-
Using constructor functions and a new operator.
Object Literals
The easiest way to create a JavaScript object is by using the object literal notation. The code sample below starts with a creation of an empty object. The second line creates an object with one property salary and assigns the value of 50000 to it. Finally, the instance of one more object pis created and the variable person points at it.
var t = {} // create an instance of an empty object var a = {salary: 50000}; // an instance with one property // Store the data about Julia Roberts var person = { lastName: ”Roberts”, firstName: ”Julia”, age: 42 };
This object has three properties: lastName, firstName, and age. Note that in object literal notation the values of these properties are specify using colon. You can access the properties of this person using the dot notation, e.g. person.LastName. But JavaScript allows yet another way of accessing the object properties by using square bracket syntax, for example person["lastName"]. In the next code sample you’ll see that using the square brackets is the only way to access the property.
var person = { "last name": "Roberts", firstName: "Julia", age: 42}; var herName=person.lastName; //console.error("Hello " + herName); //
herName=person["last name"]; //
person.salutation="Mrs. "; console.log("Hello "+ person.salutation + person["last name"]); //
| The object person doesn’t have a property lastName, but no error is thrown | |
| This will print "Hello undefined" | |
| Using and alternative way of referring to an object property | |
| This will print "Hello Mrs. Roberts" |
|
|
It’s a good idea to keep handy a style guide of any programming language, and we know two of such documents for JavaScript. Google has published their version of JavaScript Style Guide at http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml. A more detailed Airbnb JavaScript Style Guide is available as a github project at https://github.com/airbnb/javascript. |
Objects can contain other objects. If a property of an object literal is also an object, you just need to specify the value of this property in an extra pair of curly braces. For example, you can represent the telephone of a person as an object having two properties: the type and the number. The following code snippet adds a nested object to store a work phone as a nested object inside the person’s object. Run this code in the FireBug’s console and it’ll print "Call Julia at work 212-555-1212".
var p = { lastName: "Roberts", firstName: "Julia", age: 42, phone:{ type: "work", numb: "212-555-1212" } }; console.log("Call " + p.firstName + " at " + p.phone.type + " " + p.phone.numb );
What if a person has more then one phone? We can change the name of the property phone to phones and instead store an array of objects. JavaScript arrays are surrounded by square brackets, and they are zero based. The following code snippet will print "Call Julia at home 718-211-8987".
var p = { lastName: "Roberts", firstName: "Julia", age: 42, phones:[{ type: "work", numb: "212-555-1212" }, { type: "home", numb: "799-211-8987" }] }; console.log("Call " + p.firstName + " at " + p.phones[1].type + " " + p.phones[1].numb );
Methods in Object Literals
Functions defined inside objects are called methods. Defining methods in object literals is similar to defining properties - provide a method name followed by a colon and the function declaration. The code snippet below declares a method makeAppoyntment() to our object literal. Finally, the line p.makeAppointment(); invokes this new method, which will print the message on the console that Steven wants to see Julia and will call at so-and-so number.
var p = { lastName: "Roberts", firstName: "Julia", age: 42, phones:[{ type: "work", numb: "212-555-1212" }, { type: "home", numb: "718-211-8987" }], makeAppointment: function(){ console.log("Steven wants to see " + this.firstName + ". He'll call at " + this.phones[0].numb); } }; p.makeAppointment();
var greetArray=[ "Hello", prompt("Enter your name", ”Type your name here") ]; console.log(greetArray.join(","));
We’ve briefly covered object literals, and you to start using them. In Chapter 4 you’ll be learning about JSON - a popular data format used as replacement for XML in the JavaScript world. Then you’ll see how similar are the syntax of JSON and JavaScript object literals. Now we’ll spend a little bit of time delving into JavaScript functions, and then - back to objects again.
Constructor Functions
JavaScript functions are more then just some named pieces of code that implements certain behavior. They also can become objects themselves by a magic of the new operator. To make things even more intriguing, the function calls can have memories, which will be explained in the section about closures.
If a function is meant to be instantiated with the new operator it’s called a constructor function. If you are familiar with Java or C# you understand the concept of a class constructor that is being executed only once during the instantiation of a class. Now imagine that there is only a constructor without any class declaration that still can be instantiated with the new operator as in the following example.
function Person(lname, fname, age){ this.lastName=lname; this.firstName=fname; this.age=age; }; // Creating 2 instances of Person var p1 = new Person(“Roberts”,“Julia”, 42); var p2 = new Person(“Smith”, “Steven”, 34);
This code declares the function Person and after that, it creates two instances of the Person objects referred by the variables p1 and p2 accordingly. This is what the statement functions are objects means.
|
|
According to common naming conventions the names of the constructor functions are capitalized. |
Objects can have methods and properties, right? On the other hand, functions are objects. Hence functions can have methods and properties too. If you declare a function marryMe() inside the constructor function Person, marryMe() becomes a method of Person. This is exactly what we’ll do next. But this time we’ll create an HTML file that includes the <script> section referring to the JavaScript code sample located in a separate file.
If you want to try it hands-on, create a new file in your Aptana project by selecting the menu File | New | File and give it a name marryme.js. Agree with a suggested default JavaScript template, and key in the following content into this file:
function Person(lname, fname, age){ this.lastName=lname; this.firstName=fname; this.age=age; this.marryMe=function(person){ console.log("Will you marry me, " + person.firstName); }; }; var p1= new Person("Smith", "Steven"); var p2= new Person("Roberts", "Julia"); p1.marryMe(p2);
The code above uses the keyword this that refers to the object (a.k.a. context) where the code will execute. If you are familiar with the meaning of this in Java or C#, it’s similar, but not exactly the same, and we’ll illustrate it in the section titled "Who’s this". The method marryMe() of one Person object takes an instance of another Person object and makes an interesting proposition: "Will you marry me, Julia".
This time we won’t run this code in the Firebug’s console, but rather will include it in the HTML file. In Aptana, create a new File | New | File, enter marryme.html as the file name and press the button Finish. Don’t press the button Next as it’ll offer you to select from one of the HTML templates, but this would generate lots of HTML content, which is not needed for our code sample. Just type in the following in the newly created empty file marryme.html.
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <h1>Making Proposal</h1> <script src="marryme.js"></script> </body> </html>
Debudding JavaScript in Firebug
In Aptana, right-click on the file marryme.html and select the option Run As | JavaScript Web Application. We continue using Firefox as Aptana’s default browser, and you’ll see it open a new Web page that reads "Making Proposals". Open the Firebug using the View menu, refresh the page and switch to the Firebug’s tab Script. You’ll see the split panel with the JavaScript code from marryme.js on the left.
Figure 2-8. Firebug’s Script panel
Let’s set a breakpoint inside the method marryMe() by clicking in the Firebug’s gray area to the left of the line 7. You’ll see a red circle that will reveal a yellow triangle as soon as your code execution will hit this line. Refresh the content of the browser to re-run the script with a breakpoint. Now the execution stopped at line 7, the right panel contains the runtime information about the objects and variables used by your program.
Figure 2-9. Firebug’s Script panel at a breakpoint
On the top of the left panel you’ll see usual for debuggers curved arrows (Step Into, Step Over, Step Out) as well as triangular button to continue code execution. The right panel depicts the information related to this and global Window objects. In Figure 2-9 this represents the instance of the Person object represented by the variable p1 (Steven Smith). To see the content of the object, received by the method marryMe() you can add the watch variable by clicking on the text "New watch expression…" and entering person - the name of the parameter of marryMe(). Figure 2-10 shows the watch variable person (Julia Roberts) that was used during the invocation of the method marryMe().
Figure 2-10. Firebug’s Script panel at a breakpoint
Now click on the Firebug’s Net panel, which shows what goes over the network during communication between the Web browser and Web server. Figure 2-11 shows a screen shot of the Net panel where we clicked on the Headers tab for marryme.html and the Response tab of marryme.js. The code 200 for both files means that they arrived successfully to the browser. It also shows the IP address of the Web server they came from, their sizes, and plenty of other useful information. Both Script and Net panels of Firebug or any other developers tools are your best friends of any Web developer.
Figure 2-11. Firebug’s Net panel
We like Firebug, but testing and debugging should be done in several Web browsers. Besides Firebug, we’ll be using excellent Google Chrome developers tools. Their menus and panels are similar and we won’t be including such mini-tutorials on using such tools - you can easily learn them on your own.
Creating Objects Based on Other Objects
Who’s this
JavaScript and HTML Elements
After learning all these facts and techniques about the language you might be eager to see "the real use of JavaScript" – manipulating HTML elements of Web pages, which most of the people use JavaScript for. This is correct, at least today. In this section we’ll be doing exactly this – applying JavaScript code to HTML elements.
First let’s consider the operations your application needs to be able to perform inside the Web page:
-
Programmatically finding the required element by id, type, or a CSS class.
-
Changing styles of the elements (show, hide, apply fonts and colors et al.)
-
Processing events that may happen to HTML elements (click, mouseover et al.)
-
Dynamically adding or removing HTML elements from the page or changing their contents
-
Communicating with the server side, e.g. form submission or making AJAX requests for some data from the server
You need to understand how to perform these operations from JavaScript. Even if you’ll be using one of the popular frameworks, you’ll be performing the same operations applying the syntax prescribed by your framework of choice. So let’s get started.
Styling Web Pages with CSS
CSS stands for Cascading Style Sheets. During the last 15 years several CSS specifications reached the level of Recommendation by W3C: CSS Level 1, 2, and 2.1. The latest CSS Level 3 (a.k.a. CSS3) adds new features to CSS 2.1 module by module, which are listed at http://www.w3.org/Style/CSS/current-work. Brief CSS tutorial and reference is located at http://www.w3schools.com/cssref/default.asp
You can include CSS into a Web page either by linking to separate files using the HTML tag <link> or by in-lining the styles with the tag <style>. For example, if CSS is located in the file mystyles.css in the folder css add the following tag to HTML:
<link rel="stylesheet" type="text/css" href="css/mystyles.css" media="all">
The <link> tag allows specifying the media where specific css file has to be used. For example, you can have one CSS file for smartphones and another one for tablets. We’ll discuss this in detail in the section on media queries in Chapter 11.
You should put this tag in the section of your HTML before any JavaScript code to make sure that they stiles are loaded before the content of the Web page.
Placing the @import attribute inside the <style> tag allows to include styles located elsewhere:
<style> @import url (css/contactus.css) </style>
What’s the best way of including CSS in HTML? From one hand, keeping CSS in multiple files separately form HTML and JavaScript makes the code more readable and reusable. On the other hand, when if your Web site has consists of many files, the Web browser will have to make multiple round trips to your server just to load the page, which can slow down the responsiveness of your Web application.
Chapter 3. Mocking Up the Application «Save Sick Child»
The time has come to start working on our Web application Save Sick Child that will supports donations to ill children. In this chapter we’ll take care of the Web design and will create the first prototype of the Save a Child site.
Introducing Balsamic Mockups
First, we’ll create a mockup (a.k.a. wireframes) - a set of images depicting various views of our Save Sick Child application. The images may contain comments in the form of callouts that briefly explain what should change in a view if a user will make a certain action, e.g. clicks on the button. You can also think of a UI of any application as a set of states and the user’s action result in your application’s transition from one state to the other. As nerds and mathematicians say “UI of your application is a finite state machine”, which at any given point of time is in one of the finite number of states, for example, in the view state Donate Form.
Visualize yourself sitting in a cafeteria and drawing sketches of your Web site on a napkin. Well, we’ll use an electronic napkin so to speak - an excellent prototyping tool called Balsamic Mockups. This is an easy to use program. It gives you a working area where you create a mockup of your future Web application by dragging and dropping the required UI components from the toolbar onto the image of the Web page (see Figure 3-1).
Figure 3-1. The working area of Balsamiq Mockups
When the prototype is done, it can be saved as an image and sent to the project owner. Another option is to export the Balsamiq project into XML, and if both the project owner and Web designer have Balsamiq installed, the can work on it in collaboration. For example, the designer exports the current states of the project, the owner imports it and makes corrections or comments, then exports it again and sends it back to the designer.
The Project Owner Talks to a Web Designer
At this stage a Web designer talks to the project owner discussing the required functionality and then creates the UI to be implemented by Web developers. The artifacts given to developers by the designer vary depending by the qualifications of the designer. This can be a set of images representing different states of the UI with little callouts explaining the navigation of the application. If the Web designer is familiar with HTML and CSS, you may get a working prototype in the form of HTML and CSS files, and this is exactly what we’ll create by the end of this chapter.
This is what the project owner said to our designer, The Save Sick Child Web site should allow people to make donations to the ill children. The users should be able to find these children by selecting an area on the map. The site should be integrated with a payment system, include a video player and display statistics about the donors and recepients. The site should include a simple chat room and have a simple integration with Twitter and Facebook. The mockup should include three versions of the UI supporting desktops, tablets, and smartphones.''* This is what the project owner said to our designer,
The Save Sick Child Web site should allow people to make donations to the ill children. The users should be able to find these children by selecting an area on the map. The site should be integrated with a payment system, include a video player and display statistics about the donors and recipients. The site should include a simple chat room and have a simple integration with Twitter and Facebook. The mockup should include three versions of the UI supporting desktops, tablets, and smartphones.
The Web designer opened Balsamiq and started to work. She decided that the main window will consist of four areas laid out vertically: 1. A header with the logo and several navigation buttons 2. The main area with the Donate support plus the video player 3. The area with the Find Local Kid, statistics, and a chat room. 4. A footer with several house-holding links plus the icons for Twitter and FaceBook.
The First Mockups
The first deliverable of our Web designer depicted two states of the UI: before and after clicking the button Donate Now. The Web designer suggested that on the button click the Video Player would turn into a small button revealing the donation form.
Figure 3-2. The main view before clicking Donate Now. Take 1.
Figure 3-3. The main view after clicking Donate Now. Take 1.
The project owner suggested that turning the video into a button may not be a the best solution. We shouldn’t forget that the main goal of this application is collecting donation, so they decided to move the video player to the lower portion of the window. The next version of the mockup looks as shown in Figure 3-4 and 3-5. The latter shows different UI states should the user decide to log in.
Figure 3-4. The main view. Take 2.
Next comes authorization. The view states in this process are: 1. Not Logged On 2. The Login Form 3. Wrong ID/Password 4. Forgot Password 5. Successfully Logged On
The Web designer has to create a mockup for each of these states. The project owner will review them and can return them back with some comments. Figure 3-5 illustrates selected views from authorization. Due to some miscommunication the Web designer assumed that unless the user log on to the application, she won’t be able to see Save Sick Child. This is clearly wrong as the process of making donations has to be as easy as possible, and forcing the donor to log on may result in abandoning Save a Child application by some people.
Figure 3-5. Selected authorization UI states
From the Mockup to HTML Prototype
We are lucky - our Web designer knows HTML and CSS. In this section we’ll turn the still mockups into the first HTML prototype, which will use only hard-coded data but the layout of the site will be done in CSS and we’ll use HTML5 markup.
“In this book we assume that the users of our Save Sick Child site work with the latest versions of Web Browsers FireFox, Safari, Google Chrome and Internet Explorer. While in the real world Web developers need to deal with finding workarounds to the unsupported CSS or HTML5 features in the old browsers, the modern IDE generate HTML5 boilerplate code that include large CSS files providing different solutions to older browsers.”
Adding Styles With CSS
We’ve been using some CSS in short code samples from Chapter 2, and now let’s apply styles to make Save Sick Child look as in the mockup.We’ve been using some CSS in short code samples from Chapter 2, and now let’s apply styles to make Save Sick Child look as in the mockup.
Test-Driven Development with JavaScript
Idea: No more blog posts on Backbone.js or other JS frameworks without showing tests. Testing JS needs to be a bigger deal than it is.
— @bphogan
The chapter starts with a brief overview of available test frameworks. Then, it explains how to set up a new Save a Child project in the IDE using selected test framework.
Chapter 8. Replacing HTTP with WebSockets
Shaving off hundreds of bytes of HTTP overhead and reducing the latency from 150ms to 50 ms makes WebSocket worthwhile considering for any application.
This chapter starts with introducing of existing "legacy" options for creating interactive Web applications. After that we’re going to introduce Server-Sent Events (SSE) and WebSockets, which are included in HTML5 specification.
We’re going to implement monitoring of the fund-raising events and an interactive auction for our Save Sick Child application using WebSockets and Server-Sent Events. We’ll use Wireshark, a network monitoring tool, to see benefits of using WebSockets protocol.
All server-side functionality supporting this chapter is written in Java, using the Project «Tyrus» with latest Glassfish builds. If you don’t know Java, just treat this server side setup as a service that supports WebSockets. For Java developers interested in diving into the server-side, we’ll provide the source code and brief comments as a part of the code samples that come with this book.
TODO: Show the server-side data push with Server-Sent Events and WebSockets. Compare them. Do a brief overview of the Socket.IO library. Comparing sending data using WebSockets data throughput with the HTTP data push will be demonstrated in Chapter 4.
Near Realtime Applications With HTTP
The HTTP protocol is the lingua franca of today’s Web applications, where client-server communications are based on the request-response paradigm. On the low level, Web browsers establish a TCP/IP connection for each HTTP request-response session. Every time when the browser needs to send data to server and get response back the browser re-establish the TCP/IP connection. So to implement interactiveness in your application currently, there are 3 basic options that developer has to use today to satisfy the real-time client-server communication requirements. Basically, that options provide hacks on top of half-duplex HTTP protocol to simulate real-time behavior. Lets discuss each of them.
Short Polling
With short polling, your client code sends requests to the server every N seconds. The response is «empty» if there is no update as illustrated in Figure 8-1. Visualize a child seating on back seat of your car and asking, "Are we where?" every minute. And you’re politely replying "Not just yet" - compare it to a empty server response. There is no valuable payload for this kid, but she’s still receiving some "metadata". HTTP polling does the same thing that generates verbose HTTP response headers sending empty payload. Let alone destructing the driver (think the server) from performing other responsibilities.
Figure 8-1 Short polling
Long Polling
Long polling starts similarly to short polling: the client sends HTTP request to server. But in this case instead of sending an empty response (as in case with short polling), server waits till the data for the client becomes available. If the requested information is not available after the specified timeout, the server server sends an empty response to the client and closes the connection.
We’ll give you one more analogy to compare short and long polling. Imagine a party at the top floor of a building equipped with a smart elevator that goes up every minute and opens the door just in case if one of the guests wants to go down to smoke a cigarette. If no one enters the elevator, it goes to the ground level and in 60 seconds goes up again. This is the short polling scenario. But if this elevator would go up, and waited till someone would actually decided to go down, then we could call it a long polling mode.
From HTTP specification perspective this "hack" is legit: long polling server behavior indistinguishable from the «slow» server. That is why this technique also referred as "Hanging GET". If you see an online auction that automatically modifies the prices as people bid on the item it looks as if the server pushes the data to you. But most likely, this functionality was implemented using long polling, which is not a real server-side data push, but its emulation.
Figure 8-2 Long polling
TODO Compare pros and cons of long vs short polling
HTTP Streaming
Client sends the request, server wait for events and streams multipart/chunked response, and then waits for the events. The server pushes the data to the client pretending that the response never ends. The response is continually appended by the server, usually with <script> what gets executed even after the HTTP DOM object is ready
Figure 8-3 HTTP streaming
Polling and streaming can be used as a fall-back for legacy browsers that don’t support the modern HTML5 APIs Server-Sent Events and WebSockets.
Server-Sent Events
Before diving into WebSockets protocol lets get familiar with the standardized way of implementing Server-Sent Events. W3C introduces new browsers API and - EventSource object. SSE allows to subscribe to remote server events arriving in the form of DOM events. The following code snippet shows the JavaScript code that can be used in a Web browser.
var source; if( !! window.EventSource) { source = new EventSource('/donate_web/api/donations/events'); //} else { console.log("sse not supported") } source.addEventListener('open', function(e) { //
// Connection was opened. }, false); source.addEventListener('create', function(e) { //
console.log(e.data); }, false); source.addEventListener('update', function(e) { //
console.log(e.data); }, false); source.addEventListener('error', function(e) { if(e.readyState == EventSource.CLOSED) { // Connection was closed. } }, false);
| Create new EventSource object. At this point the browser will sends the GET request to the specified server-side endpoint to register itself on the server | |
| Add handlers for the open and error events | |
| Handle messages in create events | |
| Handle messages in update events |
Using SSE is a good technique for the use cases when the client doesn’t need to send the data to the server. In the above example the server sends two types of events create and update to notify subscribed clients about changing information about donation data so connected clients can monitor fund-raising process. We can create as many named-events as we want. This technique is still HTTP-based, and it requires the server’s support of a combination of HTTP 1.1 keep-alive connections and the text/event-stream content type. The overhead is minimal - instead of hundreds of bytes, the server sends only tens of bytes.
Introducing WebSockets
WebSockets is a bi-directional full-duplex socket-based protocol. The idea behind WebSockets is straightforward:
-
Establish a socket connection between the client and the server using HTTP for the initial handshake.
-
Switch the communication protocol from HTTP to direct socket-based protocol
-
Send messages in both directions simultaneously (full duplex).
-
Send messages independently. No request-response model. Both the server and the client can initiate data transmission which enables real server-push
-
Accordungly, both the server and the client can initiate disconnect.
We will explain each of this statements later in this chapter while introducing WebSocket API.
IETF RFC 6455 Protocol
WebSocket introduces the new protocol URI’s: ws and wss for secured web-socket connection.
WebSockets Interface
To define an abstract Web socket interface the expert group uses Interface Description Language
[Constructor(DOMString url, optional (DOMString or DOMString[]) protocols)] //interface WebSocket : EventTarget { readonly attribute DOMString url; // ready state const unsigned short CONNECTING = 0; const unsigned short OPEN = 1; const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; readonly attribute unsigned long bufferedAmount; // networking [TreatNonCallableAsNull] attribute Function? onopen; [TreatNonCallableAsNull] attribute Function? onerror; [TreatNonCallableAsNull] attribute Function? onclose; readonly attribute DOMString extensions; readonly attribute DOMString protocol; void close([Clamp] optional unsigned short code, optional DOMString reason); // messaging [TreatNonCallableAsNull] attribute Function? onmessage; attribute DOMString binaryType; void send(DOMString data); void send(ArrayBufferView data); void send(Blob data); };
| The constructor requires an endpoint URI and optional sub-protocols name. |
Client-Side API
After the introduction of the WebSockets interface lets see how the client’s JavaScript can use it.
var ws; if(window.WebSocket) { //console.log("WebSocket object is supported in your browser"); ws = new WebSocket("ws://www.websocket.org/echo"); //
ws.onopen = function() { console.log("onopen"); }; //
ws.onmessage = function(e) { console.log("echo from server : " + e.data); //
}; ws.onclose = function() { //
output("onclose"); }; ws.onerror = function() { output("onerror"); //
}; } else { output("WebSocket object is not supported in your browser"); }
| Check if the WebSocket object is supported by the browser. | |
| Instantiate the new WebSocket object with passing endpoint URI as constructor parameter. | |
| Set event handlers for open, message, close events. | |
| e.data property of the message event contains the received message. | |
| handle closing connection … | |
| … and errors |
WebSockets Handshake
Handshake upgrades the connection from HTTP to the WebSockets protocol. It’s an upgrade to a message based communication. We will discuss messages (a.k.a. frames) later in this chapter. Why upgrading from HTTP instead of starting with the TCP as a protocol in the first place? The reason is that the WebSockets operates on the same ports (80 and 443) as HTTP and HTTPS do. It’s an advantage because all ports under 1024 are privileged, and they are handled differently than non privileged ones.
For instance, on Linux systems only the user with root privileges can create a socket on such ports. WebSockets use the same port as HTTP/HTTPS and it make this much more interesting. Another example would be the Flash Player socket policy system that will attempt to connect to port 843 to get the authorization information.
We have to tunnel our communication through the HTTP because arbitrary socket connections may not be allowed by the various firewalls for security or scalability reasons. In most of the cases, HTTP connections via ports 80 or 443 are allowed where the TCP socket connections are not. Also many corporate networks only allow certain ports outgoing. And HTTP/HTTPS ports are usually included in so called white lists.
The protocol upgrade is initiated by the client request, which also transmits a special key with the upgrade request. The server processes this request and send back a confirmation for the upgrade. This ensures that a WebSocket connection cannot be established with an endpoint that is not aware of the WebSockets protocol. Here is what the handshake looks can like in the client’s request:
GET HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: echo.websocket.org
Origin: http://www.websocket.org
Sec-WebSocket-Key: i9ri+AfOgSsKwUlmLjIkGA==
Sec-WebSocket-Version: 13
This client sends the GET request for the protocol upgrade. The Sec-WebSocket_Key is just a set of random bytes. The server takes these bytes and appends to it a special Global Unique Identifier (GUID) string 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, then creates theSecure Hash Algorithm SHA1 hash from it followed by the base64 encoding. The resulting string of bytes needs to be used by both the server and the client, and it’s unlikely that this string will be used by the network endpoints that do not understand the WebSockets protocol. Then this value would be copieded in the Sec-WebSocket-Accept header field. When the server has computed the value it can send the response back confirming the protocol upgrade.
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: Qz9Mp4/YtIjPccdpbvFEm17G8bs=
Access-Control-Allow-Origin: http://www.websocket.org
The WebSockets protocol uses the 400 Bad Request error to signal the missing upgrade. The handshake can also include a protocol request and the WebSocket version information but you can’t include arbitrary other headers. We can’t transmit the authorization information. There are two ways around this. You can either transmit the authorization information as the first request (e.g. unique clientId can be passed as part of the HTTP response header or HTML wrapper) or put it into the URL as a query parameter during the initial handshake. Consider the following example.
var clientId = AppContext.getClientId(); //ws = new WebSocket("ws://www.websocket.org/echo/"+clientID); //
![]()
| Here we’re getting clientId value from the AppContext singleton object. | |
| We’re connecting to the WebSockets endpoint with an extra URI parameter which will be stored on server for future interactions. |
Because WebSockets protocol creates a bi-directional (socket-to-socket) connection server has access to conversation session associated with the new web socket connection. This session can be associated with clientId and be stored on server.
The WebSocket frame anatomy
In this section we’re going to explore how the WebSocket data transfer works. The WebSocket is not a stream based protocol like TCP - it’s message based. The difference is that with TCP a program sends the bytes and has to ensure that the end of a message can be recognized. The WebSocket specification makes it easier because it puts a frame around everything. It’s easy to do from the JavaScript on the client, but it’s harder to handle in the server side code because it needs to wrap everything in frames. The frame can look like this:
+-+-+-+-+-------+-+-------------+-------------------------------+ 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+
-
FIN (1 bit)
This bit indicates if this frame is the final frame that makes up the message. Most of the time the message fits into a single frame and this bit will always be set.
-
RSV1, RSV2, RSV3 (1 bit each)
These bits are the reserved for future protocol changes and improvements. They must contain zeros as they are not being used at this time.
-
opcode (4 bits)
-
0x00 This frame continues the payload from the last.
-
0x01 This frame includes utf-8 text data.
-
0x02 This frame includes binary data.
-
0x08 This frame terminates the connection
-
0x09 This frame is a Ping.
-
0x10 This frame is a Pong.
-
mask (1 bit)
-
This indicates if the frame is masked.
-
payload_len (7 bits, 7+16 bits, or 7+64 bits)
The length of the payload. WebSocket frames come in the following length brackets: 0-125 indicate the length of the payload. 126 means that the following two bytes indicate the length. ** 127 means the next 8 bytes indicate the length.
-
masking-key (32 bits)
This key is used to XOR the payload with.
-
payload
This indicates the actual masked data. The length of block is defined in the payload_len bits.
more TBD
The Heartbeats
Certain things like transparent and explicit proxy servers or a content-filtering hardware can terminate the idle connections or a remote side could go down. Only on the next send your program can realize that something went wrong. With WebSockets the browser can send the ping opcode 0x9 at any time to ask the other side to pong back (the opcode 0xA).
Pings can be sent whenever required, but a pong may sent at server’s discretion. If an endpoint receives a Ping frame and has not yet sent Pong frame(s) in response to the previous Ping frame(s), the endpoint can elect to send a Pong frame for only the most recently processed Ping frame. The Ping frame may contain the application data (can be up to 125 bytes) and Pong must have identical data in message body.
There is no Javascript API to send Ping frames or receive Pongs frames. This is either supported by your browser, or not. There is also no API to enable, configure or detect whether the browser supports and is using Ping/Pong frames.
TODO - Client-side frameworks - Server-side API
WebSocket Use Cases
WebSockets really shine with following applications:
-
Live trading/auctions/sports notifications
-
Controlling medical equipment over the web
-
Chat applications
-
Multi-player online games
-
Real-time updates in social streams
For the "Save Sick Child" application we’re going to use WebSockets to implement an online auction communication layer. The goal is to let individuals and businesses purchase hand-made crafts and arts made by the children. All proceeds will go to help sick children.
Protocols Considerations for Enterprise Applications
The downside: WebSockets specification gives you only the transport, but it doesn’t include the application-level protocol. Developers need to invent the application-specific text or binary protocols. For example, the auction bid has to be presented in a form agreed upon by all application modules. Let’s discuss our options from protocol modeling perspective.
-
SOAP, XML, XSD
-
REST, JSON, CSV
TODO
WebSockets and Proxies
HTTP always supported upgrades, but unfortunately many proxies seem to have ignored that part of the specification. The main reason for that probably is that until WebSockets came around no one was actually using the Upgrade flag.
WebSockets and HTTP 2.0
"I use the metaphor of hammers and screwdrivers. Both tools are indispensable in my workshop…
Use the right tool for the job. In the case of page and object delivery use SPDY. In the case of lightweight or streaming data delivery look to WebSocket."
— Chief Product Architect at Akamai
-
http 2.0, spdy, websockets
-
framed protocols (describe frames)
Part 2: Mobile
Responsive Design: One Site Fits All
The chapter starts with a brief overview of different approaches to making the Web site to the mobile space. One of the approaches is having only one Web site for all devices. This approach is is called Responsive Design, and we’ll modify the design of the Save a Child site to introduce different layouts for the desktop, tablet, and smartphone devices. By the end of this chapter the site Save a Child will automatically change its layout based on the user’s device without the losing any functionality.
Why Having One Code Base is Better
If an enterprise decided to develop separate versions of the Web application - one for the desktop and another for mobile devices - the Web server can be configured to perform redirection to the appropriate code. Web servers can do it based on the value of the USER_AGENT attribute of the HTTP request’s header. For example, the mobile Web browsers of our Save a Child application would get the content from the URL m.saveachild.org while the desktop users would get it from saveachild.org. You can program such USER_AGENT based redirection in your JavaScript too, but it’s better to do this on the server level.
We prefer to have to use responsive design and have only one location for the code for both desktop and mobile applications. There is another practical reason for not having different versions of the code. Most likely your Web application will use some third-party JavaScript framework. At some point you may run into a bug and need to upgrade the mobile version to use the latest version of such frameworks, say jQuery.But the desktop version works just fine. In case of having two separate versions of the application you’ll have to either upgrade jQuery and thoroughly test both mobile and desktop versions of Save a Child, or live with two different versions of jQuery. In case of responsive design, there is only one code base and one upgrade of jQuery to be made.
Let’s spend a little more time discussing the USER_AGENT attribute.
There is a Web site called useragentstring.com. It lists hundreds of strings representing possible content of the USER_AGENT attribute for a plethora of mobile devices. It’s impossible to create different layout of your Web application for each of them.
By the way, have you ever tried to share the link of the Web site from your iPhone? It' so easy! Just press the button and enter the email of the person to share the site with. Got to cnn.com on your iPhone and share this link with someone. That person will receive the link m.cnn.com, and if she’s visit this site from the desktop it won’t look nice as it’s a stripped version that was intended to be watched on the mobile phone.
The Content on Desktop vs Mobile
TODO